#ifndef _FADT_H_
#define _FADT_H_
+#include <xen/hvm/ioreq.h>
+
//
// FADT Definitions, see ACPI 2.0 specification for details.
//
//
// Fixed Feature Flags
//
-#define ACPI_FIXED_FEATURE_FLAGS (ACPI_PROC_C1|ACPI_SLP_BUTTON|ACPI_WBINVD|ACPI_PWR_BUTTON|ACPI_FIX_RTC)
+#define ACPI_FIXED_FEATURE_FLAGS (ACPI_PROC_C1 | ACPI_SLP_BUTTON | \
+ ACPI_WBINVD | ACPI_PWR_BUTTON | \
+ ACPI_FIX_RTC | ACPI_TMR_VAL_EXT)
//
// PM1A Event Register Block Generic Address Information
#define ACPI_PM1A_EVT_BLK_ADDRESS_SPACE_ID ACPI_SYSTEM_IO
#define ACPI_PM1A_EVT_BLK_BIT_WIDTH 0x20
#define ACPI_PM1A_EVT_BLK_BIT_OFFSET 0x00
-#define ACPI_PM1A_EVT_BLK_ADDRESS 0x000000000000c010
//
// PM1B Event Register Block Generic Address Information
#define ACPI_PM1A_CNT_BLK_ADDRESS_SPACE_ID ACPI_SYSTEM_IO
#define ACPI_PM1A_CNT_BLK_BIT_WIDTH 0x10
#define ACPI_PM1A_CNT_BLK_BIT_OFFSET 0x00
-#define ACPI_PM1A_CNT_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x04)
//
// PM1B Control Register Block Generic Address Information
#define ACPI_PM_TMR_BLK_ADDRESS_SPACE_ID ACPI_SYSTEM_IO
#define ACPI_PM_TMR_BLK_BIT_WIDTH 0x20
#define ACPI_PM_TMR_BLK_BIT_OFFSET 0x00
-#define ACPI_PM_TMR_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x08)
//
// General Purpose Event 0 Register Block Generic Address
obj-y += i8254.o
obj-y += i8259.o
obj-y += rtc.o
+obj-y += pmtimer.o
obj-y += instrlen.o
obj-y += intercept.o
obj-y += io.o
#include <asm/mc146818rtc.h>
#include <asm/spinlock.h>
#include <asm/hvm/hvm.h>
-#include <asm/hvm/vpit.h>
+#include <asm/hvm/vpt.h>
#include <asm/hvm/support.h>
#include <public/sched.h>
#include <public/hvm/ioreq.h>
pt_timer_fn, v, v->processor);
pit_init(v, cpu_khz);
rtc_init(v, RTC_PORT(0), RTC_IRQ);
+ pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS);
}
void pic_irq_request(void *data, int level)
#include <asm/hvm/hvm.h>
#include <asm/hvm/io.h>
#include <asm/hvm/support.h>
-#include <asm/hvm/vpit.h>
+#include <asm/hvm/vpt.h>
#include <asm/current.h>
/* Enable DEBUG_PIT may cause guest calibration inaccuracy */
#include <asm/shadow.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
-#include <asm/hvm/vpit.h>
+#include <asm/hvm/vpt.h>
#include <asm/hvm/vpic.h>
#include <asm/hvm/vlapic.h>
--- /dev/null
+#include <asm/hvm/vpt.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/support.h>
+
+#define TMR_STS (1 << 0)
+static void pmt_update_status(void *opaque)
+{
+ PMTState *s = opaque;
+ s->pm1_status |= TMR_STS;
+
+ /* TODO: When TMR_EN == 1, generate a SCI event */
+
+ set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER);
+}
+
+static int handle_pmt_io(ioreq_t *p)
+{
+ struct vcpu *v = current;
+ PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt;
+ uint64_t curr_gtime;
+
+ if (p->size != 4 ||
+ p->pdata_valid ||
+ p->type != IOREQ_TYPE_PIO){
+ printk("HVM_PMT: wrong PM timer IO\n");
+ return 1;
+ }
+
+ if (p->dir == 0) { /* write */
+ /* PM_TMR_BLK is read-only */
+ return 1;
+ } else if (p->dir == 1) { /* read */
+ curr_gtime = hvm_get_guest_time(s->vcpu);
+ s->pm1_timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32;
+ p->u.data = s->pm1_timer;
+ s->last_gtime = curr_gtime;
+ return 1;
+ }
+ return 0;
+}
+
+void pmtimer_init(struct vcpu *v, int base)
+{
+ PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt;
+
+ s->pm1_timer = 0;
+ s->pm1_status = 0;
+ s->scale = ((uint64_t)FREQUENCE_PMTIMER << 32) / ticks_per_sec(v);
+ s->vcpu = v;
+
+ init_timer(&s->timer, pmt_update_status, s, v->processor);
+ /* ACPI supports a 32-bit power management timer */
+ set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER);
+
+ register_portio_handler(base, 4, handle_pmt_io);
+}
+
+void pmtimer_deinit(struct domain *d)
+{
+ PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
+
+ kill_timer(&s->timer);
+}
*/
#include <asm/mc146818rtc.h>
-#include <asm/hvm/vpit.h>
+#include <asm/hvm/vpt.h>
#include <asm/hvm/io.h>
#include <asm/hvm/support.h>
#include <asm/current.h>
kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer);
rtc_deinit(d);
+ pmtimer_deinit(d);
if ( d->arch.hvm_domain.shared_page_va )
unmap_domain_page_global(
struct periodic_time *pt =
&(v->domain->arch.hvm_domain.pl_time.periodic_tm);
struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
+ struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt;
if ( pt->enabled )
{
migrate_timer(&VLAPIC(v)->vlapic_timer, v->processor);
migrate_timer(&vrtc->second_timer, v->processor);
migrate_timer(&vrtc->second_timer2, v->processor);
+ migrate_timer(&vpmt->timer, v->processor);
}
kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer);
rtc_deinit(d);
+ pmtimer_deinit(d);
if ( d->arch.hvm_domain.shared_page_va )
unmap_domain_page_global(
{
struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
+ struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt;
if ( pt->enabled )
{
migrate_timer(&VLAPIC(v)->vlapic_timer, v->processor);
migrate_timer(&vrtc->second_timer, v->processor);
migrate_timer(&vrtc->second_timer2, v->processor);
+ migrate_timer(&vpmt->timer, v->processor);
}
static void vmx_store_cpu_guest_regs(
#define __ASM_X86_HVM_DOMAIN_H__
#include <asm/hvm/vpic.h>
-#include <asm/hvm/vpit.h>
+#include <asm/hvm/vpt.h>
#include <asm/hvm/vlapic.h>
#include <asm/hvm/vioapic.h>
#include <public/hvm/params.h>
+++ /dev/null
-/*
- * vpit.h: Virtual PIT definitions
- *
- * Copyright (c) 2004, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef __ASM_X86_HVM_VPIT_H__
-#define __ASM_X86_HVM_VPIT_H__
-
-#include <xen/config.h>
-#include <xen/init.h>
-#include <xen/lib.h>
-#include <xen/time.h>
-#include <xen/errno.h>
-#include <xen/time.h>
-#include <xen/timer.h>
-#include <asm/hvm/vpic.h>
-
-#define PIT_FREQ 1193181
-#define PIT_BASE 0x40
-
-typedef struct PITChannelState {
- int count; /* can be 65536 */
- u16 latched_count;
- u8 count_latched;
- u8 status_latched;
- u8 status;
- u8 read_state;
- u8 write_state;
- u8 write_latch;
- u8 rw_mode;
- u8 mode;
- u8 bcd; /* not supported */
- u8 gate; /* timer start */
- s64 count_load_time;
- /* irq handling */
- struct vcpu *vcpu;
- struct periodic_time *pt;
-} PITChannelState;
-
-typedef struct PITState {
- PITChannelState channels[3];
- int speaker_data_on;
- int dummy_refresh_clock;
-} PITState;
-
-#define RTC_SIZE 14
-typedef struct RTCState {
- uint8_t cmos_data[RTC_SIZE]; /* Only handle time/interrupt part in HV */
- uint8_t cmos_index;
- struct tm current_tm;
- int irq;
- /* second update */
- int64_t next_second_time;
- struct timer second_timer;
- struct timer second_timer2;
- struct vcpu *vcpu;
- struct periodic_time *pt;
-} RTCState;
-
-/*
- * Abstract layer of periodic time, one short time.
- */
-typedef void time_cb(struct vcpu *v, void *opaque);
-
-struct periodic_time {
- char enabled; /* enabled */
- char one_shot; /* one shot time */
- char irq;
- char first_injected; /* flag to prevent shadow window */
- u32 pending_intr_nr; /* the couner for pending timer interrupts */
- u32 period; /* frequency in ns */
- u64 period_cycles; /* frequency in cpu cycles */
- s_time_t scheduled; /* scheduled timer interrupt */
- u64 last_plt_gtime; /* platform time when last IRQ is injected */
- struct timer timer; /* ac_timer */
- time_cb *cb;
- void *priv; /* ponit back to platform time source */
-};
-
-struct pl_time { /* platform time */
- struct periodic_time periodic_tm;
- struct PITState vpit;
- struct RTCState vrtc;
- /* TODO: ACPI time */
-};
-
-static __inline__ s_time_t get_scheduled(
- struct vcpu *v, int irq,
- struct periodic_time *pt)
-{
- if ( is_irq_enabled(v, irq) ) {
- return pt->scheduled;
- }
- else
- return -1;
-}
-
-extern u64 hvm_get_guest_time(struct vcpu *v);
-/*
- * get processor time.
- * unit: TSC
- */
-static __inline__ int64_t hvm_get_clock(struct vcpu *v)
-{
- uint64_t gtsc;
-
- gtsc = hvm_get_guest_time(v);
- return gtsc;
-}
-
-#define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency)
-
-/* to hook the ioreq packet to get the PIT initialization info */
-extern void hvm_hooks_assist(struct vcpu *v);
-extern void pickup_deactive_ticks(struct periodic_time *vpit);
-extern struct periodic_time *create_periodic_time(u32 period, char irq, char one_shot, time_cb *cb, void *data);
-extern void destroy_periodic_time(struct periodic_time *pt);
-void pit_init(struct vcpu *v, unsigned long cpu_khz);
-void rtc_init(struct vcpu *v, int base, int irq);
-void rtc_deinit(struct domain *d);
-int is_rtc_periodic_irq(void *opaque);
-void pt_timer_fn(void *data);
-void pit_time_fired(struct vcpu *v, void *priv);
-
-#endif /* __ASM_X86_HVM_VPIT_H__ */
--- /dev/null
+/*
+ * vpt.h: Virtual Platform Timer definitions
+ *
+ * Copyright (c) 2004, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef __ASM_X86_HVM_VPT_H__
+#define __ASM_X86_HVM_VPT_H__
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/time.h>
+#include <xen/errno.h>
+#include <xen/time.h>
+#include <xen/timer.h>
+#include <asm/hvm/vpic.h>
+
+#define PIT_FREQ 1193181
+#define PIT_BASE 0x40
+
+typedef struct PITChannelState {
+ int count; /* can be 65536 */
+ u16 latched_count;
+ u8 count_latched;
+ u8 status_latched;
+ u8 status;
+ u8 read_state;
+ u8 write_state;
+ u8 write_latch;
+ u8 rw_mode;
+ u8 mode;
+ u8 bcd; /* not supported */
+ u8 gate; /* timer start */
+ s64 count_load_time;
+ /* irq handling */
+ struct vcpu *vcpu;
+ struct periodic_time *pt;
+} PITChannelState;
+
+typedef struct PITState {
+ PITChannelState channels[3];
+ int speaker_data_on;
+ int dummy_refresh_clock;
+} PITState;
+
+#define RTC_SIZE 14
+typedef struct RTCState {
+ uint8_t cmos_data[RTC_SIZE]; /* Only handle time/interrupt part in HV */
+ uint8_t cmos_index;
+ struct tm current_tm;
+ int irq;
+ /* second update */
+ int64_t next_second_time;
+ struct timer second_timer;
+ struct timer second_timer2;
+ struct vcpu *vcpu;
+ struct periodic_time *pt;
+} RTCState;
+
+#define FREQUENCE_PMTIMER 3579545
+typedef struct PMTState {
+ uint32_t pm1_timer;
+ uint32_t pm1_status;
+ uint64_t last_gtime;
+ struct timer timer;
+ uint64_t scale;
+ struct vcpu *vcpu;
+} PMTState;
+
+/*
+ * Abstract layer of periodic time, one short time.
+ */
+typedef void time_cb(struct vcpu *v, void *opaque);
+
+struct periodic_time {
+ char enabled; /* enabled */
+ char one_shot; /* one shot time */
+ char irq;
+ char first_injected; /* flag to prevent shadow window */
+ u32 pending_intr_nr; /* the couner for pending timer interrupts */
+ u32 period; /* frequency in ns */
+ u64 period_cycles; /* frequency in cpu cycles */
+ s_time_t scheduled; /* scheduled timer interrupt */
+ u64 last_plt_gtime; /* platform time when last IRQ is injected */
+ struct timer timer; /* ac_timer */
+ time_cb *cb;
+ void *priv; /* ponit back to platform time source */
+};
+
+struct pl_time { /* platform time */
+ struct periodic_time periodic_tm;
+ struct PITState vpit;
+ struct RTCState vrtc;
+ struct PMTState vpmt;
+};
+
+static __inline__ s_time_t get_scheduled(
+ struct vcpu *v, int irq,
+ struct periodic_time *pt)
+{
+ if ( is_irq_enabled(v, irq) ) {
+ return pt->scheduled;
+ }
+ else
+ return -1;
+}
+
+extern u64 hvm_get_guest_time(struct vcpu *v);
+/*
+ * get processor time.
+ * unit: TSC
+ */
+static __inline__ int64_t hvm_get_clock(struct vcpu *v)
+{
+ uint64_t gtsc;
+
+ gtsc = hvm_get_guest_time(v);
+ return gtsc;
+}
+
+#define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency)
+
+/* to hook the ioreq packet to get the PIT initialization info */
+extern void hvm_hooks_assist(struct vcpu *v);
+extern void pickup_deactive_ticks(struct periodic_time *vpit);
+extern struct periodic_time *create_periodic_time(u32 period, char irq, char one_shot, time_cb *cb, void *data);
+extern void destroy_periodic_time(struct periodic_time *pt);
+void pit_init(struct vcpu *v, unsigned long cpu_khz);
+void rtc_init(struct vcpu *v, int base, int irq);
+void rtc_deinit(struct domain *d);
+void pmtimer_init(struct vcpu *v, int base);
+void pmtimer_deinit(struct domain *d);
+int is_rtc_periodic_irq(void *opaque);
+void pt_timer_fn(void *data);
+void pit_time_fired(struct vcpu *v, void *priv);
+
+#endif /* __ASM_X86_HVM_VPT_H__ */
}; /* sizeof this structure must be in one page */
typedef struct buffered_iopage buffered_iopage_t;
+#define ACPI_PM1A_EVT_BLK_ADDRESS 0x000000000000c010
+#define ACPI_PM1A_CNT_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x04)
+#define ACPI_PM_TMR_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x08)
+
#endif /* _IOREQ_H_ */
/*